package common.util;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by ibm on 2018/8/26.
 */
class AsyncRetryableTask extends RetryableTask
{
    /**
     * 单位是秒数
     */
    private long timeout;
    private ThreadPoolExecutor threadPoolExecutor;

    public AsyncRetryableTask(long timeout, ThreadPoolExecutor threadPoolExecutor)
    {
        this.timeout = timeout;
        this.threadPoolExecutor = threadPoolExecutor;
    }

    /**
     * 使用传入的线程池异步执行任务，并且等待。
     * <p/>
     * future.get()方法，等待指定的毫秒数。如果任务在超时时间内结束，则正常返回。
     * 如果抛异常（可能是执行超时、执行异常、被其他线程cancel或interrupt），都记录日志并且网上抛异常。
     * 正常和非正常的情况都会判断任务是否结束，如果没有结束，则cancel任务。cancel参数为true，表示即使
     * 任务正在执行，也会interrupt线程。
     */
    @Override
    protected <T> T doTask(Callable<T> callable) throws Exception
    {
        Future<T> future = threadPoolExecutor.submit(callable);
        try
        {
            return future.get(timeout, TimeUnit.MILLISECONDS);
        } catch (Exception e)
        {
            RetryableTasks.LOG.warn("Try once failed", e);
            throw e;
        } finally
        {
            if (!future.isDone())
            {
                future.cancel(true);
                RetryableTasks.LOG.warn("Try once task not done, cancel it, active count: " + threadPoolExecutor.getActiveCount());
            }
        }
    }
}
